/** 应用程序配置类
 * @file config.cpp
 * @author Kiven Lee
 * @version 1.0
 * @date 2021-08-09
 *
 * @copyright Copyright Kivensoft (c) 2021
 *
 */
#include "config.hpp"

#include <cstdarg>
#include <getopt.h>
#include <charconv>

#include "klib/argparse.hpp"
#include "klib/ansicolor.hpp"
#include "klib/log.hpp"
#include "kwin/strconv.hpp"

using namespace klib;

namespace {
    const char LOG_FILE[] = "miniplayer.log";
    const char LOG_LEVEL[] = "debug";
    const char LOG_SIZE[] = "10485760";
    const char STATIC_DIR[] = "static";
    const char NODE_DLL[] = "node.dll";
    const char INDEX_HTML[] = "html\\index.html";

    const char ARG_DEBUG[] = "debug";
    const char ARG_HELP[] = "help";
    const char ARG_LOG_FILE[] = "log-file";
    const char ARG_LOG_LEVEL[] = "log-level";
    const char ARG_LOG_SIZE[] = "log-size";
    const char ARG_NODE_DLL[] = "node-dll";
    const char ARG_INDEX_HTML[] = "index-html";
}

static arg_option gArgOptons[] = {
    {'d',  ARG_DEBUG,      arg_option::NoArg,  nullptr,    "设置为调试模式"},
    {'h',  ARG_HELP,       arg_option::NoArg,  nullptr,    "打印帮助信息并退出"},
    {'F',  ARG_LOG_FILE,   arg_option::HasArg, LOG_FILE,   "设置日志文件名(example: " AC_Y("logs/miniplayer.log") ")"},
    {'L',  ARG_LOG_LEVEL,  arg_option::HasArg, LOG_LEVEL,  "设置日志级别[trace/debug/info/warn/error/off]"},
    {'\0', ARG_LOG_SIZE,   arg_option::HasArg, LOG_SIZE,   "设置日志文件大小[k/m/g]"},
    {'N',  ARG_NODE_DLL,   arg_option::HasArg, NODE_DLL,   "设置node.dll所在目录"},
    {'I',  ARG_INDEX_HTML, arg_option::HasArg, INDEX_HTML, "设置index.html路径"},
    {'\0', nullptr}};

static uint32_t parse_size(const char* size) {
    if (!size) return 0;
    uint32_t ret = 0, unit;
    std::size_t len = std::strlen(size);
    char c = size[len - 1];
    switch (c) {
        case 'k': case 'K': unit = 1024; break;
        case 'm': case 'M': unit = 1024 * 1024; break;
        case 'g': case 'G': unit = 1024 * 1024 * 1024; break;
        default: unit = 0; break;
    }
    if (c < '0' || c > '9') --len;
    std::from_chars(size, size + len, ret);
    return ret * unit;
}

static inline const char* _conv_if_null(const char* src) {
    return src ? src : "";
}

bool miniplayer::Config::parse(int argc, char* const argv[]) {
    arg_parse argParse(gArgOptons);
    if (!argParse.parse(argc, argv) || argParse.get(ARG_HELP)) {
        miniplayer::Config::usage();
        return false;
    }

    _debug = argParse.get(ARG_DEBUG) != nullptr;
    _node_dll = _conv_if_null(argParse.get(ARG_NODE_DLL));
    _index_html = _conv_if_null(argParse.get(ARG_INDEX_HTML));

    // 设置http服务静态文件路径
    if (_work.length() == 0) _webroot = STATIC_DIR;
    else _webroot = _work + STATIC_DIR;

    // 设置日志级别及输出的日志文件
    klib::log_t::set_level(argParse.get(ARG_LOG_LEVEL));
    const char* log_name = argParse.get(ARG_LOG_FILE);
    klib::log_t::set_file(log_name, parse_size(argParse.get(ARG_LOG_SIZE)));

    return true;
}

void miniplayer::Config::usage() {
    char title[512];
    klib::snprintf(title, sizeof(title),
            AC_Y("%s") " Version " AC_G("%s") "\nCopyRight (C) Kivensoft 2017-2021\n" AC_C("%s"),
            app, ver, desc);
    title[sizeof(title) - 1] = '\0';
    arg_parse argParse(gArgOptons);
    argParse.usage(title, app);
}
